package com.jade.explorer.dirscan;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import com.jade.logger.Logger;

public class FileSystem {

	/**
	 * This method removes file or directory from file system
	 * @param path <code>String</code> path to file or directory
	 */
	public static boolean removeFile(String path){
		File file = new File(path);
		return file.delete();
	}
	
	
	/**
	 * This method recursively removes folder and all subdirectories and files in this folder
	 * @param path path to folder
	 * @return returns true if folder successfully removed
	 */
	public static boolean removeFolder(String path){
		
		File dir = new File(path);
		
		if (dir.isDirectory()){
			

			if (dir.list().length > 0);{
				for (File f : dir.listFiles()){
					removeFolder(f.getPath());
				}
			}
		
			if (dir.list().length == 0){
				return dir.delete();
			}
		}	
		
		if(dir.isFile()){
			return dir.delete();
		}
		
		return false;
	}
	
	
	/**
	 * This method create new object in current directory with specified tags
	 * @param path <code>String</code> path to directory
	 */
	public static void createNewObject(String path){
		File file = new File(path);
		if (!file.exists())
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
	}
	
	
	/**
	 * This method create new domain in current directory with specified tags
	 * @param path <code>String</code> path to directory
	 */
	public static void createNewDomain(String path){
		//TODO create new domain
	}
	
	
	/**
	 * This method create new anisotropy in current directory with specified tags
	 * @param path <code>String</code> path to directory
	 */
	public static void createNewAnisotropy(String path){
		//TODO create new anisotropy
	}
	
	
	/**
	 * This method create new folder in current directory with specified tags
	 * @param path <code>String</code> path to directory
	 */
	public static void createNewFolder(String path){
		//TODO create new folder 
	}
	
	/**
	 * This method check string for forbidden symbols
	 * @param input <code>String</code> input string
	 * @return <code>true</code> if string doesn't contains any of forbidden symbols 
	 */
	public static boolean checkInput(String input){
		if(input == null) input = "";
		if(input.indexOf("<") > -1) return false;
		if(input.indexOf(">") > -1) return false;
		if(input.indexOf("/") > -1) return false;
		if(input.indexOf("\\") > -1) return false;
		if(input.indexOf("*") > -1) return false;
		if(input.indexOf(":") > -1) return false;
		if(input.indexOf("?") > -1) return false;
		if(input.indexOf("\"") > -1) return false;
		if(input.indexOf("|") > -1) return false;
		if(input.indexOf(".") > -1) return false;
		return true;
	}
	
	/**
	 * This method allows to copy file to directory
	 * @param filePath - Path to file which will be copied
	 * @param dirPath - Path to directory where this file will be copied
	 * @return false if file already exist or another mistake
	 */
	public static String copyFileOver(String filePath, String dirPath){
		File file = new File(filePath);
		File dir = new File(dirPath + "//" + file.getName());
		
		try {
			InputStream in = new FileInputStream(file);
			OutputStream out = new FileOutputStream(dir);
			
			byte[] buf = new byte[1024];
			int len;
			try {
				while ((len = in.read(buf)) > 0){
					out.write(buf, 0, len);
				}
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
			try {
				in.close();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		}
		
		return dir.getAbsoluteFile().toString();
	}
	
	
	/**
	 * This method allows to copy file to directory
	 * @param filePath - Path to file which will be copied
	 * @param dirPath - Path to directory where this file will be copied
	 * @return false if file already exist or another mistake
	 */
	public static String copyFileNoOver(String filePath, String dirPath){
		File file = new File(filePath);
		File dir = new File(dirPath + "//" + file.getName());
		
		if (dir.exists()) return dir.getAbsoluteFile().toString();
		
		try {
			InputStream in = new FileInputStream(file);
			OutputStream out = new FileOutputStream(dir);
			
			byte[] buf = new byte[1024];
			int len;
			try {
				while ((len = in.read(buf)) > 0){
					out.write(buf, 0, len);
				}
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
			try {
				in.close();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		}
		
		return dir.getAbsoluteFile().toString();
	}
	
	
	/**
	 * This method allows to copy file to directory with overwriting existing files
	 * @param filePath - Path to file which will be copied
	 * @param dirPath - Path to directory where this file will be copied
	 * @return false if file already exist or another mistake
	 */
	public static boolean copyFileToWithOverwrite(String filePath, String dirPath){
		File file = new File(filePath);
		File dir = new File(dirPath + "//" + file.getName());
		
		try {
			InputStream in = new FileInputStream(file);
			OutputStream out = new FileOutputStream(dir);
			
			byte[] buf = new byte[1024];
			int len;
			try {
				while ((len = in.read(buf)) > 0){
					out.write(buf, 0, len);
				}
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}
			try {
				in.close();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return false;
		}
		
		return true;
	}
	
	
	/**
	 * This method allows to copy file to directory without overwriting existing files
	 * @param filePath - Path to file which will be copied
	 * @param dirPath - Path to directory where this file will be copied
	 * @return false if file already exist or another mistake
	 */
	public static boolean copyFileToWithNoOverwrite(String filePath, String dirPath){
		File file = new File(filePath);
		File dir = new File(dirPath + "//" + file.getName());
		
		if (dir.exists()) return true;
		
		try {
			InputStream in = new FileInputStream(file);
			OutputStream out = new FileOutputStream(dir);
			
			byte[] buf = new byte[1024];
			int len;
			try {
				while ((len = in.read(buf)) > 0){
					out.write(buf, 0, len);
				}
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}
			try {
				in.close();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return false;
		}
		
		return true;
	}
	
	
	/**
	 * This method allows to copy file to directory with new name
	 * @param filePath - Path to file which will be copied
	 * @param dirPath - Path to directory where this file will be copied
	 * @return false if file already exist or another mistake
	 */
	public static String copyFileWithName(String filePath, String dirPath, String newName){
		File file = new File(filePath);
		File dir = new File(dirPath + "//" + newName);
		
		try {
			InputStream in = new FileInputStream(file);
			OutputStream out = new FileOutputStream(dir);
			
			byte[] buf = new byte[1024];
			int len;
			try {
				while ((len = in.read(buf)) > 0){
					out.write(buf, 0, len);
				}
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
			try {
				in.close();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		}
		
		return dir.getAbsoluteFile().toString();
	}
	
	
	public static boolean createProjectSctucture(String local, String name){
		String path = local + "\\" + name;
		String obj = path + "\\Objects";
		String ani = path + "\\Placement";
		String dom = path + "\\Anisotropy";
		try{
			
			if (new File(path).exists()){
				Logger.print(Logger.STATE_ERROR, "Project already exists");
				return false;
			}
				
			
			boolean s1 = new File(path).mkdir();
			boolean s2 = new File(obj).mkdir();
			boolean s3 = new File(ani).mkdir();
			boolean s4 = new File(dom).mkdir();
			
			if (s1 && s2 && s3 && s4)
				return true;
			
		}catch (Exception e){
			Logger.print(Logger.STATE_ERROR, "Cant create project directory");
		}
		return false;
	}
	
	
	private static boolean copyDirAllWithOver(File dirIn, File dirOut){
		
		for (File f : dirIn.listFiles()){
			if (f.isDirectory()){
				File dirNew = new File(dirOut + "\\" + f.getName());
				if(!dirNew.exists()){
					dirNew.mkdir();
				}
				if (f.list().length > 0){
					for (File fl : f.listFiles()){
						if(fl.isDirectory()){
							if(!copyDirAllWithOver(fl, dirNew))
								return false;
						}
						if(fl.isFile()){
							if (!copyFileToWithOverwrite(fl.getPath(), dirNew.getPath()))
								return false;
						}
					}
				}
					
			}
			if (f.isFile()){	
				if (!copyFileToWithOverwrite(f.getPath(), dirOut.getPath()))
					return false;
			}
		}
		
		return true;
	}
	
	
	public static boolean copyFilderWithOverwritingExistingFiles(String dirInPath, String dirOutPath){
	
		File dirIn = new File(dirInPath);
		File dirOut = new File (dirOutPath + "\\" + dirIn.getName());
		dirOut.mkdir();
		
		return copyDirAllWithOver(dirIn, dirOut);
		
	}
	
	
	
	private static boolean copyDirAllWithNoOver(File dirIn, File dirOut){
		
		for (File f : dirIn.listFiles()){
			if (f.isDirectory()){
				File dirNew = new File(dirOut + "\\" + f.getName());
				if(!dirNew.exists()){
					dirNew.mkdir();
				}
				if (f.list().length > 0){
					for (File fl : f.listFiles()){
						if(fl.isDirectory()){
							if(!copyDirAllWithOver(fl, dirNew))
								return false;
						}
						if(fl.isFile()){
							if (!copyFileToWithNoOverwrite(fl.getPath(), dirNew.getPath()))
								return false;
						}
					}
				}
					
			}
			if (f.isFile()){	
				if (!copyFileToWithNoOverwrite(f.getPath(), dirOut.getPath()))
					return false;
			}
		}
		
		return true;
	}
	
	
	public static boolean copyFilderWithNoOverwritingExistingFiles(String dirInPath, String dirOutPath){
		
		File dirIn = new File(dirInPath);
		File dirOut = new File (dirOutPath + "\\" + dirIn.getName());
		dirOut.mkdir();
		
		return copyDirAllWithNoOver(dirIn, dirOut);		
	}
	
}
